﻿
namespace Patterns4Net.PatternEnforcer.Cmd.Output
{
    using System.Collections.Generic;
    using System.Diagnostics.Contracts;
    using Mono.Cecil;
    using System.IO;
    using Core;

    /// <summary>
    /// Generates output that conforms format expected by Visual Studio.
    /// </summary>
    public class VisualStudioOutput : IOutputFormatter    
	{
		private bool showWarnings;
	
		public VisualStudioOutput(bool showWarnings = false)
		{
			this.showWarnings = showWarnings;
		}

        public void Start(TextWriter writer)
        {
        }

        public void Print(IEnumerable<PatternEnforcer.ResultItem> result, TextWriter writer)
        {
            foreach (var resultItem in result)
            {
                string memberName = GetMemberName(resultItem);

                foreach (var checkerResultPair in resultItem.CheckerResults)
                {
                    var pattern = checkerResultPair.Key;
                    var checkerResult = checkerResultPair.Value;                    
                    if (checkerResult.IsValid == false)
                    {
                        foreach (var error in checkerResult.Errors)
                        {
                            writer.WriteLine(
                                "{0} The implementation of pattern {1} in {2} seems not to be valid. Reason: {3}", 
								this.GetBeginning(),
                                pattern.Name,
                                memberName,
                                error.Message);
                        }
                    }
                }
            }
        }

        public void End(TextWriter writer)
        {
        }

        private string GetBeginning() 
		{
			return this.showWarnings ? "Warning:" : "Error:";
		}

        private static string GetMemberName(PatternEnforcer.ResultItem resultItem)
        {
            if (resultItem.Member is MethodDefinition)
            {
                return string.Format("{0}.{1}", resultItem.Member.DeclaringType.Name, resultItem.Member.Name);
            }

            if (resultItem.Member is TypeDefinition)
            {
                return resultItem.Member.Name;
            }

            Contract.Assert(
                false,
                string.Format("OuputResultCommandLine unexpected member type {0}", resultItem.Member.GetType()));
            return resultItem.Member.ToString();
        }
    }
}
